package cn.skyquant.quant4j.service.boot.web.interceptor;

import cn.skyquant.quant4j.api.account.AccountDTO;
import cn.skyquant.quant4j.api.authority.UserDTO;
import cn.skyquant.quant4j.api.dto.ResultDTO;
import cn.skyquant.quant4j.sdk.util.log.LogUtil;
import cn.skyquant.quant4j.sdk.util.string.StringUtils;
import cn.skyquant.quant4j.service.boot.model.authority.AppContext;
import cn.skyquant.quant4j.service.boot.model.authority.RoleAuthority;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

/**
 * service层的拦截器校验，以后再说
 */
@Aspect
@Component
public class ServiceSecurity  {
    public final static ResultDTO no_permission = ResultDTO.error("no permission");
    @Autowired
    AppContext appContext;

    @Pointcut("@within(authority)")
    public void pointcut(RoleAuthority authority) {
    }

    @Around("pointcut(authority)")
    public Object around(ProceedingJoinPoint joinPoint, RoleAuthority authority) {
        Signature signature = joinPoint.getSignature();
        boolean canProceed = false;
        UserDTO loginUser = appContext.get();
        AccountDTO accountDTO = appContext.getAccount();
        //只要加了这个注解，那么必须是登录用户才可以访问
        if(loginUser!=null){
            String[] roleNames = authority.roleNames();
            if(roleNames==null || roleNames.length==0){
                canProceed = true;
            }else{
                canProceed = loginUser.containAny(roleNames);
            }
        }
        if(accountDTO!=null){
            canProceed = true;
        }
        if(canProceed){
            try {
                return joinPoint.proceed();
            } catch (Throwable throwable) {
                LogUtil.error(String.format("%s error:%s",signature.toString(),throwable.getMessage()));
                return ResultDTO.error;
            }
        }else {
            if(loginUser==null){
                LogUtil.error(String.format("no login user, can't access %s",signature.toString()));
            }else {
                String rolestr = StringUtils.join(authority.roleNames(),"[","]");
                LogUtil.error(String.format("user[%s].role:%s, access %s need role:%s , forbidden!",loginUser.tel,loginUser.getRoles(),signature.toShortString(),rolestr));
            }
        }
        return no_permission;
    }
}
